#!/bin/bash

# KingbaseES V9 简化安装脚本
# 去掉复杂的进度显示，直接安装并输出日志

set -e

# 默认配置
INSTALL_DIR="/KingbaseES/V9"
DATA_DIR="/data"
DB_PORT="54321"
DB_USER="system"
DB_PASS="kingbase"
KINGBASE_USER="kingbase"
DATABASE_MODE="Oracle"
ISO_PATH=""

# 日志文件（通过参数设置或使用默认值）
LOG_FILE=""

# 全局变量记录需要清理的资源
ISO_MOUNT_DIR=""
ROLLBACK_SCRIPT=""
CREATED_RESOURCES=()

# 日志函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

log_error() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1" | tee -a "$LOG_FILE"
}

# 详细日志函数
log_detail() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [DETAIL] $1" >> "$LOG_FILE"
}

# 记录配置变更
log_config_change() {
    local file="$1"
    local description="$2"
    log_detail "配置变更: $file - $description"
}

# 清理函数
cleanup() {
    local exit_code=$?
    
    if [[ $exit_code -ne 0 ]]; then
        echo
        log_error "安装过程异常退出 (退出码: $exit_code)"
    fi
    
    # 清理ISO挂载
    if [[ -n "$ISO_MOUNT_DIR" && -d "$ISO_MOUNT_DIR" ]]; then
        log "清理ISO挂载点: $ISO_MOUNT_DIR"
        umount "$ISO_MOUNT_DIR" 2>/dev/null || true
        rmdir "$ISO_MOUNT_DIR" 2>/dev/null || true
        log_detail "已清理ISO挂载点: $ISO_MOUNT_DIR"
    fi
    
    # 如果安装失败且生成了回退脚本，询问是否执行回退
    if [[ $exit_code -ne 0 && -f "$ROLLBACK_SCRIPT" ]]; then
        echo
        echo "安装失败！已生成回退脚本: $ROLLBACK_SCRIPT"
        read -p "是否立即执行回退操作？(y/N): " -n 1 -r
        echo
        if [[ $REPLY =~ ^[Yy]$ ]]; then
            log "开始执行回退操作..."
            bash "$ROLLBACK_SCRIPT"
        else
            echo "回退脚本已保存，您可以稍后手动执行: bash $ROLLBACK_SCRIPT"
        fi
    fi
    
    exit $exit_code
}

# 信号处理
handle_signal() {
    local signal="$1"
    echo
    log_error "收到信号: $signal，开始清理资源..."
    exit 130
}

# 设置信号处理
trap cleanup EXIT
trap 'handle_signal INT' INT
trap 'handle_signal TERM' TERM

# 显示使用方法
show_usage() {
    cat << EOF
KingbaseES V9 简化安装脚本

使用方法:
    $0 -f ISO文件路径 [其他选项]

选项:
    -f FILE        指定ISO文件路径 (必需)
    -m MODE        数据库兼容模式 (Oracle|MySQL|SQL Server, 默认: Oracle)
    -i DIR         安装目录 (默认: /KingbaseES/V9)
    -d DIR         数据目录 (默认: /data)
    -p PORT        数据库端口 (默认: 54321)
    -u USER        数据库用户名 (默认: system)
    -P PASS        数据库密码 (默认: kingbase)
    -U USER        系统用户名 (默认: kingbase)
    -l FILE        日志文件路径 (默认: 自动生成)
    -h             显示帮助信息

示例:
    $0 -f /soft/KingbaseES_V009R004C012B0006_Lin64_install.iso
    $0 -f /soft/kingbase.iso -m "SQL Server" -p 5432 -i /opt/kingbase
    $0 -f /soft/kingbase.iso -d /var/data -u admin -P mypassword
EOF
}

# 解析参数
while getopts "f:m:i:d:p:u:P:U:l:h" opt; do
    case $opt in
        f)
            ISO_PATH="$OPTARG"
            ;;
        m)
            DATABASE_MODE="$OPTARG"
            ;;
        i)
            INSTALL_DIR="$OPTARG"
            ;;
        d)
            DATA_DIR="$OPTARG"
            ;;
        p)
            DB_PORT="$OPTARG"
            ;;
        u)
            DB_USER="$OPTARG"
            ;;
        P)
            DB_PASS="$OPTARG"
            ;;
        U)
            KINGBASE_USER="$OPTARG"
            ;;
        l)
            LOG_FILE="$OPTARG"
            ;;
        h)
            show_usage
            exit 0
            ;;
        \?)
            echo "无效选项: -$OPTARG"
            show_usage
            exit 1
            ;;
    esac
done

# 检查必需参数
if [[ -z "$ISO_PATH" ]]; then
    echo "错误: 必须指定ISO文件路径"
    show_usage
    exit 1
fi

# 设置默认日志文件（如果没有通过-l指定）
if [[ -z "$LOG_FILE" ]]; then
    LOG_FILE="./kingbase_simple_install_$(date +%Y%m%d_%H%M%S).log"
fi

# 设置回退脚本路径
ROLLBACK_SCRIPT="./kingbase_rollback_$(date +%Y%m%d_%H%M%S).sh"

# 初始化回退脚本
init_rollback_script() {
    cat > "$ROLLBACK_SCRIPT" << 'EOF'
#!/bin/bash

# KingbaseES 安装回退脚本
# 自动生成，用于回退安装过程中的所有变更

set -e

echo "开始回退 KingbaseES 安装..."

# 记录回退操作
rollback_log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] ROLLBACK: $1"
}

EOF
    chmod +x "$ROLLBACK_SCRIPT"
    log "回退脚本已初始化: $ROLLBACK_SCRIPT"
    log_detail "回退脚本路径: $ROLLBACK_SCRIPT"
}

# 添加回退命令到脚本
add_rollback_cmd() {
    local cmd="$1"
    local description="$2"
    
    cat >> "$ROLLBACK_SCRIPT" << EOF

# $description
rollback_log "$description"
if $cmd; then
    rollback_log "成功: $description"
else
    rollback_log "失败: $description"
fi
EOF
    
    log_detail "添加回退命令: $description -> $cmd"
}

# 验证参数
if [[ ! "$DATABASE_MODE" =~ ^(Oracle|MySQL|SQL Server)$ ]]; then
    echo "错误: 不支持的数据库模式: $DATABASE_MODE"
    echo "支持的模式: Oracle, MySQL, SQL Server"
    exit 1
fi

if [[ ! "$DB_PORT" =~ ^[0-9]+$ ]] || [[ "$DB_PORT" -lt 1024 ]] || [[ "$DB_PORT" -gt 65535 ]]; then
    echo "错误: 端口必须是1024-65535之间的数字: $DB_PORT"
    exit 1
fi

# 检查目录路径
if [[ "$INSTALL_DIR" == "/" ]] || [[ "$DATA_DIR" == "/" ]]; then
    echo "错误: 安装目录和数据目录不能是根目录"
    exit 1
fi

# 检查ISO文件
if [[ ! -f "$ISO_PATH" ]]; then
    log_error "ISO文件不存在: $ISO_PATH"
    exit 1
fi

# 检查root权限
if [[ $EUID -ne 0 ]]; then
    log_error "此脚本需要root权限运行"
    exit 1
fi

# 初始化回退脚本
init_rollback_script

log "开始KingbaseES V9安装"
log "配置信息:"
log "  ISO文件: $ISO_PATH"
log "  兼容模式: $DATABASE_MODE"
log "  安装目录: $INSTALL_DIR"
log "  数据目录: $DATA_DIR"
log "  数据库端口: $DB_PORT"

log_detail "===== 开始安装过程详细记录 ====="

# 1. 配置密码策略 (必须在创建用户前执行)
log "步骤1: 配置密码策略"
log_detail "备份原始PAM配置文件"
cp /etc/pam.d/system-auth /etc/pam.d/system-auth.kingbase.backup
add_rollback_cmd "cp /etc/pam.d/system-auth.kingbase.backup /etc/pam.d/system-auth && rm -f /etc/pam.d/system-auth.kingbase.backup" "恢复PAM密码策略配置"

log_detail "禁用pam_pwquality密码复杂度检查"
sed -i 's/^password\s\+requisite\s\+pam_pwquality.so/#&/g' /etc/pam.d/system-auth
log_config_change "/etc/pam.d/system-auth" "注释掉pam_pwquality行"

log_detail "移除use_authtok参数"
sed -i 's/use_authtok$//' /etc/pam.d/system-auth
log_config_change "/etc/pam.d/system-auth" "移除use_authtok参数"

log "密码复杂度要求已禁用"

# 2. 创建kingbase用户
log "步骤2: 创建用户和组"
if ! id "$KINGBASE_USER" &>/dev/null; then
    log_detail "创建系统用户: $KINGBASE_USER"
    useradd -d "/home/$KINGBASE_USER" -m "$KINGBASE_USER"
    add_rollback_cmd "userdel -r $KINGBASE_USER 2>/dev/null || true" "删除创建的用户 $KINGBASE_USER"
    
    log_detail "设置用户密码"
    echo "$KINGBASE_USER:$KINGBASE_USER" | chpasswd
    log_config_change "/etc/passwd" "添加用户 $KINGBASE_USER"
    log_config_change "/etc/shadow" "设置用户 $KINGBASE_USER 密码"
    log_config_change "/home/$KINGBASE_USER" "创建用户主目录"
    
    log "用户 $KINGBASE_USER 创建成功"
    CREATED_RESOURCES+=("user:$KINGBASE_USER")
else
    log "用户 $KINGBASE_USER 已存在"
    log_detail "跳过用户创建，用户已存在"
fi

# 3. 创建目录
log "步骤3: 创建安装目录"
REQUIRED_DIRS=("$INSTALL_DIR" "$DATA_DIR" "/backup" "/archive" "/install")

for dir in "${REQUIRED_DIRS[@]}"; do
    if [[ ! -d "$dir" ]]; then
        log_detail "创建目录: $dir"
        mkdir -p "$dir"
        add_rollback_cmd "rm -rf $dir" "删除创建的目录 $dir"
        CREATED_RESOURCES+=("dir:$dir")
        log_config_change "$dir" "创建目录"
    else
        log_detail "目录已存在: $dir"
    fi
done

log_detail "设置目录所有者为: $KINGBASE_USER"
chown -R "$KINGBASE_USER:$KINGBASE_USER" "${REQUIRED_DIRS[@]}"
log_config_change "${REQUIRED_DIRS[*]}" "设置目录所有者为 $KINGBASE_USER"

log_detail "设置目录权限"
chmod -R 775 "$INSTALL_DIR" "/backup" "/archive" "/install"
chmod -R 700 "$DATA_DIR"
log_config_change "$INSTALL_DIR /backup /archive /install" "设置权限为755"
log_config_change "$DATA_DIR" "设置权限为700"

log "目录创建完成"

# 4. 禁用防火墙
log "步骤4: 配置防火墙"
systemctl stop firewalld || true
systemctl disable firewalld || true
log "防火墙已禁用"

# 5. 配置系统参数
log "步骤5: 配置系统参数"

# 内核参数
cat >> /etc/sysctl.conf << EOF
# KingbaseES parameters
fs.aio-max-nr=1048576
fs.file-max=6815744
kernel.shmall=4194304
kernel.shmmax=17179869184
kernel.shmmni=4096
kernel.sem=250 32000 100 128
net.ipv4.ip_local_port_range=9000 65500
EOF
sysctl -p >> "$LOG_FILE" 2>&1

# 系统限制
cat >> /etc/security/limits.conf << EOF
# KingbaseES limits
$KINGBASE_USER soft nofile 65536
$KINGBASE_USER hard nofile 65536
$KINGBASE_USER soft nproc 65536
$KINGBASE_USER hard nproc 65536
EOF

# systemd配置
sed -i 's/#RemoveIPC=no/RemoveIPC=no/' /etc/systemd/logind.conf
systemctl daemon-reload
systemctl restart systemd-logind.service
log "系统参数配置完成"

# 6. 挂载并提取ISO
log "步骤6: 处理ISO文件"
ISO_MOUNT_DIR="/tmp/kingbase_iso_$$"
log_detail "创建ISO挂载点: $ISO_MOUNT_DIR"
mkdir -p "$ISO_MOUNT_DIR"

log_detail "挂载ISO文件: $ISO_PATH -> $ISO_MOUNT_DIR"
if mount -o loop "$ISO_PATH" "$ISO_MOUNT_DIR" >> "$LOG_FILE" 2>&1; then
    log_config_change "$ISO_MOUNT_DIR" "挂载ISO文件"
    
    log_detail "复制ISO内容到安装目录: /install"
    cp -r "$ISO_MOUNT_DIR"/* /install/
    log_config_change "/install" "复制ISO文件内容"
    
    log_detail "卸载ISO文件"
    umount "$ISO_MOUNT_DIR"
    rmdir "$ISO_MOUNT_DIR"
    ISO_MOUNT_DIR=""  # 清空变量，避免重复清理
    
    log_detail "设置安装文件所有者"
    chown -R "$KINGBASE_USER:$KINGBASE_USER" /install
    log_config_change "/install" "设置所有者为 $KINGBASE_USER"
    
    log "ISO文件处理完成"
else
    log_error "ISO文件挂载失败"
    exit 1
fi

# 7. 配置环境变量
log "步骤7: 配置环境变量"
cat > "/home/$KINGBASE_USER/.bash_profile" << EOF
# KingbaseES environment
export KES_HOME=$INSTALL_DIR/Server
export LD_LIBRARY_PATH=\$KES_HOME/lib:/lib:/usr/lib:/usr/lib64
export PATH=\$KES_HOME/bin:\$PATH
EOF
chown "$KINGBASE_USER:$KINGBASE_USER" "/home/$KINGBASE_USER/.bash_profile"
log "环境变量配置完成"

# 8. 创建静默安装配置
log "步骤8: 创建安装配置文件"
# 设置更大的临时目录避免/tmp空间不足
export TEMP_DIR="/install/temp"
mkdir -p "$TEMP_DIR"
chown "$KINGBASE_USER:$KINGBASE_USER" "$TEMP_DIR"

cat > /install/setup/silent.cfg << EOF
KB_LICENSE_PATH=
CHOSEN_INSTALL_SET=Full
CHOSEN_FEATURE_LIST=SERVER,KSTUDIO,KDTS,INTERFACE,DEPLOY
USER_INSTALL_DIR=$INSTALL_DIR
USER_SELECTED_DATA_FOLDER=$DATA_DIR
DB_PORT=$DB_PORT
DB_USER=$DB_USER
DB_PASS=$DB_PASS
DB_PASS2=$DB_PASS
ENCODING_PARAM=UTF8
LOCALE_PARAM=zh_CN.UTF-8
DATABASE_MODE_PARAM=$DATABASE_MODE
BLOCK_SIZE_PARAM=8k
AUTHENTICATION_METHOD_PARAM=scram-sha-256
TEMP_FOLDER_PARAM=$TEMP_DIR
EOF
chown "$KINGBASE_USER:$KINGBASE_USER" /install/setup/silent.cfg
log "安装配置文件创建完成"

# 9. 执行安装
log "步骤9: 执行数据库安装"
cd /install
# 设置临时目录环境变量避免/tmp空间不足
export TMPDIR="$TEMP_DIR"
export TMP="$TEMP_DIR"
export TEMP="$TEMP_DIR"
sudo -u "$KINGBASE_USER" bash -c "export TMPDIR='$TEMP_DIR' TMP='$TEMP_DIR' TEMP='$TEMP_DIR' && ./setup.sh -i silent -f /install/setup/silent.cfg" >> "$LOG_FILE" 2>&1

if [[ ${PIPESTATUS[0]} -eq 0 ]]; then
    log "数据库安装成功"
else
    log_error "数据库安装失败"
    exit 1
fi

# 10. 启动数据库
log "步骤10: 启动数据库服务"
sudo -u "$KINGBASE_USER" bash -c "source /home/$KINGBASE_USER/.bash_profile && sys_ctl start -D $DATA_DIR" >> "$LOG_FILE" 2>&1

if [[ ${PIPESTATUS[0]} -eq 0 ]]; then
    log "数据库启动成功"
else
    log_error "数据库启动失败"
    exit 1
fi

# 11. 验证安装
log "步骤11: 验证安装"
if [[ -f "$INSTALL_DIR/Server/bin/ksql" ]]; then
    log "安装验证成功: ksql 可执行文件存在"
    # 获取版本信息
    VERSION_OUTPUT=$(sudo -u "$KINGBASE_USER" bash -c "source /home/$KINGBASE_USER/.bash_profile && ksql -V 2>/dev/null")
    if [[ $? -eq 0 && -n "$VERSION_OUTPUT" ]]; then
        log "版本验证成功: $VERSION_OUTPUT"
    else
        log "版本信息获取失败，但安装文件存在"
    fi
else
    log_error "验证失败: ksql 可执行文件不存在"
fi

log "=================================="
log "KingbaseES V9 安装完成"
log "=================================="
log "连接信息:"
log "  主机: localhost"
log "  端口: $DB_PORT"
log "  用户: $DB_USER"
log "  密码: $DB_PASS"
log "=================================="
log "连接命令:"
log "su - $KINGBASE_USER"
log "ksql -p $DB_PORT -U $DB_USER kingbase"
log "=================================="

# 完善回退脚本结尾
cat >> "$ROLLBACK_SCRIPT" << 'EOF'

rollback_log "回退操作完成"
echo "回退操作已完成！"
EOF

log_detail "===== 安装过程详细记录结束 ====="
log "安装成功! 回退脚本已生成: $ROLLBACK_SCRIPT"

echo "安装完成! 详细日志请查看: $LOG_FILE"